package com.ruoyi.web.controller.system;

import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * UDP发送和接收的单类实现（含多线程处理接收）
 */
public class UdpCommunicator {
    private final int targetPort;       // 目标端口
    private final String targetIp;      // 目标IP
    private final int localPort;        // 本地监听端口
    private DatagramSocket socket;      // UDP套接字
    private boolean isRunning = false;  // 运行状态标记

    // 构造方法：指定目标IP、目标端口和本地监听端口
    public UdpCommunicator(String targetIp, int targetPort, int localPort) {
        this.targetIp = targetIp;
        this.targetPort = targetPort;
        this.localPort = localPort;
    }

    /**
     * 启动UDP通信（初始化套接字并启动接收线程）
     */
    public void start() throws SocketException {
        // 创建并绑定套接字到本地端口
        socket = new DatagramSocket(localPort);
        isRunning = true;
        System.out.println("UDP通信已启动，本地监听端口：" + localPort +
                "，目标：" + targetIp + ":" + targetPort);

        // 启动接收线程（单独线程处理阻塞接收）
        new Thread(this::receive, "UDP接收线程").start();
    }

    /**
     * 接收数据的方法（阻塞操作，需在单独线程中运行）
     */
    private void receive() {
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (isRunning) {
            try {
                // 阻塞等待接收数据
                socket.receive(packet);

                // 解析接收的数据
                String data = new String(
                        packet.getData(),
                        0,
                        packet.getLength(),
                        StandardCharsets.UTF_8
                );

                // 打印接收信息
                System.out.println("\n收到来自 " + packet.getAddress().getHostAddress() +
                        ":" + packet.getPort() + " 的数据：" + data);

            } catch (Exception e) {
                if (isRunning) { // 非主动关闭时打印异常
                    System.err.println("接收数据出错：" + e.getMessage());
                }
            }
        }
    }

    /**
     * 发送数据的方法
     * @param message 要发送的消息
     */
    public void send(String message) throws Exception {
        if (!isRunning || socket == null) {
            throw new IllegalStateException("UDP通信未启动，请先调用start()方法");
        }

        // 构建发送数据包
        byte[] data = message.getBytes(StandardCharsets.UTF_8);
        InetAddress targetAddress = InetAddress.getByName(targetIp);
        DatagramPacket packet = new DatagramPacket(
                data,
                data.length,
                targetAddress,
                targetPort
        );

        // 发送数据
        socket.send(packet);
        System.out.println("已发送：" + message);
    }

    /**
     * 停止UDP通信
     */
    public void stop() {
        isRunning = false;
        if (socket != null && !socket.isClosed()) {
            socket.close(); // 关闭套接字会中断receive()的阻塞
        }
        System.out.println("UDP通信已停止");
    }

    // 测试方法
    public static void main(String[] args) {
        try {
            // 本地测试：目标IP为本地，目标端口8888，本地监听端口9999
            UdpCommunicator udp = new UdpCommunicator("127.0.0.1", 8888, 9999);
            udp.start();

            // 从控制台输入并发送数据
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入要发送的消息（输入exit退出）：");
            while (true) {
                String input = scanner.nextLine();
                if ("exit".equalsIgnoreCase(input)) {
                    break;
                }
                udp.send(input);
            }

            // 停止通信并关闭资源
            udp.stop();
            scanner.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

